﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PH.Model.Schools;
using PH.Model.Accounts;
namespace PH.Data.Schools
{
    public class SchoolCommand
    {
        public static void SaveCheck(SchoolModel school, DBCentre db)
        {
            if (string.IsNullOrEmpty(school.SchoolName))
                throw new Utils.PhException("请提供学校名称");
            if (school.OwnerGuid==Guid.Empty)
                throw new Utils.PhException("请提供学校的所属机构");
            if (string.IsNullOrEmpty(school.Code))
                throw new Utils.PhException("请提供学校的编码");
            if (db != null)
            {
                if (db.DataContext.Schools.Any(p => p.SchoolName == school.SchoolName && p.Guid != school.Guid))
                    throw new Utils.PhException("学校名称重复");
                if (db.DataContext.Schools.Any(p => p.Code == school.Code && p.Guid != school.Guid))
                    throw new Utils.PhException("学校编码重复");
            }
        }

        public static SchoolModel CreateNewSchool(SchoolModel school)
        {
            if (school != null)
            {
                school.CreatedOn = DateTime.Now;
                school.Guid = Guid.NewGuid();
                var bureaus = Systems.BureauCommand.GetParents(school.OwnerGuid);
                using (DBCentre db = new DBCentre())
                {
                    SaveCheck(school, db);
                    var dSchool = Convertor.ConvertFrom<School,SchoolModel>(school);

                    #region 关联学校与教育局的关系
                    var owner = db.DataContext.Bureaus.FirstOrDefault(p => p.Guid == school.OwnerGuid);
                    if (owner != null)
                    {
                        dSchool.SchoolInBureaux.Add(new SchoolInBureau()
                        {
                            BureauID = owner.ID,
                            IsDirect = true
                        });

                        if (bureaus != null && bureaus.Count > 0)
                        {
                            bureaus.ForEach(p =>
                            {
                                dSchool.SchoolInBureaux.Add(new SchoolInBureau()
                                {
                                    BureauID=p.ID
                                });
                            });
                        }
                    }
                    else
                        throw new Utils.PhException("此学校没有直属机关。");
                    
                    #endregion

                    db.DataContext.Schools.Add(dSchool);

                    #region 创建一个学校管理员用户
                    var userName = Utils.Password.MakeRandomPassword("LOWER", 8);
                    while (db.DataContext.Users.Any(p => p.UserName == userName))
                    {
                        userName = Utils.Password.MakeRandomPassword("LOWER", 8);
                        System.Threading.Thread.Sleep(100);
                    }
                    var user = new User()
                    {
                        Guid = Guid.NewGuid(),
                        UserName = userName,
                        Password = Utils.Encrypt.MD5Encrypt("888888"),
                        RealName = "管理员",
                        Status = 1,
                        CreatedOn = DateTime.Now,
                        AssociatedSchoolID = dSchool.ID
                    };
                    var role = db.DataContext.Roles.FirstOrDefault(p => p.RoleName == "SchoolAdmin");
                    user.Roles.Add(role);
                    db.DataContext.Users.Add(user);
                    #endregion

                    db.DataContext.SaveChanges();
                    school.ID = dSchool.ID;
                    return school;
                }
            }
            return null;
        }

        public static void UpdateSchool(SchoolModel school)
        {
            if (school != null && school.Guid!=Guid.Empty)
            {
                var bureaus = Systems.BureauCommand.GetParents(school.OwnerGuid);
                using (DBCentre db = new DBCentre())
                {
                    var dSchool = db.DataContext.Schools.FirstOrDefault(p => p.Guid==school.Guid);
                    if (dSchool != null)
                    {
                        SaveCheck(school, db);
                        Convertor.UpdateValue(school, dSchool);

                        #region 关联学校与教育局的关系
                        var owner = db.DataContext.Bureaus.FirstOrDefault(p => p.Guid == school.OwnerGuid);
                        if (owner != null)
                        {
                            db.Delete<SchoolInBureau>(p => p.SchoolID == dSchool.ID);
                            dSchool.SchoolInBureaux.Add(new SchoolInBureau()
                            {
                                BureauID = owner.ID,
                                IsDirect = true
                            });

                            if (bureaus != null && bureaus.Count > 0)
                            {
                                bureaus.ForEach(p =>
                                {
                                    dSchool.SchoolInBureaux.Add(new SchoolInBureau()
                                    {
                                        BureauID = p.ID
                                    });
                                });
                            }
                        }
                        else
                            throw new Utils.PhException("此学校没有直属机关。");

                        #endregion

                        db.DataContext.SaveChanges();
                    }
                    else
                        throw new Utils.PhException("不存在的学校");
                }
            }
        }

        public static void DeleteSchool(Guid guid)
        {
            if (guid != Guid.Empty)
            {
                using (DBCentre db = new DBCentre())
                {
                    var d = db.DataContext.Schools.FirstOrDefault(p => p.Guid == guid);
                    if (d != null)
                    {
                        db.DataContext.Schools.Remove(d);
                        db.DataContext.SaveChanges();
                    }
                }
            }
        }

        public static SchoolModel GetSchool(Guid guid)
        {
            if (guid != Guid.Empty)
            {
                using (DBCentre db = new DBCentre())
                {
                    var dSchool = db.DataContext.Schools.FirstOrDefault(p => p.Guid == guid);
                    if (dSchool != null)
                    {
                        var school = Convertor.ConvertTo<SchoolModel,School>(dSchool);
                        var owner = db.DataContext.Bureaus.FirstOrDefault(p => p.SchoolInBureaux.Any(o => o.SchoolID == school.ID && o.IsDirect));
                        if (owner != null)
                            school.OwnerGuid = owner.Guid;
                        return school;
                    }
                }
            }
            return null;   
        }
        public static SchoolModel GetSchool(int id)
        {
            if (id>0)
            {
                using (DBCentre db = new DBCentre())
                {
                    var dSchool = db.DataContext.Schools.FirstOrDefault(p => p.ID==id);
                    if (dSchool != null)
                    {
                        var school = Convertor.ConvertTo<SchoolModel, School>(dSchool);
                        var owner = db.DataContext.Bureaus.FirstOrDefault(p => p.SchoolInBureaux.Any(o => o.SchoolID == school.ID && o.IsDirect));
                        if (owner != null)
                            school.OwnerGuid = owner.Guid;
                        return school;
                    }
                }
            }
            return null;
        }

        public static SchoolCollection GetSchools(SchoolQuery search)
        {
            var result = new SchoolCollection();
            using (DBCentre db = new DBCentre())
            {
                IQueryable<School> q = db.DataContext.Schools.Where(p => !p.IsRemove);
                var n = 0;

                if (!string.IsNullOrEmpty(search.Key))
                    q = q.Where(p => p.SchoolName.Contains(search.Key));
                if (!string.IsNullOrEmpty(search.AreaCode))
                    q = q.Where(p => p.AreaCode.StartsWith(search.AreaCode));
                if (search.OwnerID > 0)
                    q = q.Where(p => p.SchoolInBureaux.Any(o => o.BureauID == search.OwnerID && o.IsDirect));
                if (search.BureauID > 0)
                    q = q.Where(p => p.SchoolInBureaux.Any(o => o.BureauID == search.BureauID));
                q = q.OrderBy(p => p.Code);
                if (search.PageSize > 0)
                {
                    n = q.Count();
                    q = q.Skip(search.PageSize * search.PageIndex).Take(search.PageSize);
                }
                var lst = q.ToList();
                result = Convertor.ConvertCollection<SchoolModel, School, SchoolCollection>(lst);
                result.TotalRecordsCount = n == 0 ? lst.Count : n;

                result.ForEach(p =>
                {
                    var d = lst.Find(o => o.ID == p.ID);
                    if (search.GetSchoolType)
                        p.SchoolType = d.SchoolType.Description;
                    if (search.GetPersonCount)
                        p.PersonCount = d.Students.Count();
                    if (search.GetUser)
                    {
                        var u = d.Users.FirstOrDefault(r => r.Roles.Any(o => o.RoleName == "SchoolAdmin"));
                        p.User = Convertor.ConvertTo<UserModel, User>(u);
                    }
                });
            }
            return result;
        }

        public static List<int> GetSchoolIDs(int bureauID)
        {
            using (DBCentre db = new DBCentre())
            {
                var q = db.DataContext.SchoolInBureaux.Where(p => p.BureauID == bureauID);
                return q.Select(p => p.SchoolID).ToList();
            }
        }

        public static void Remove(Guid guid)
        {
            if (guid != Guid.Empty)
            {
                using (DBCentre db = new DBCentre())
                {
                    var sch = db.DataContext.Schools.FirstOrDefault(p => p.Guid == guid);
                    sch.IsRemove = true;
                    db.DataContext.SaveChanges();
                }
            }
        }
    }
}
